// Copyright (c) Microsoft Corporation.  All rights reserved.

#include "stdafx.h"
#include "D3D11InfoQueue.h"

using namespace msclr::interop;
using namespace Microsoft::WindowsAPICodePack::DirectX::Direct3D11;

void InfoQueue::AddApplicationMessage(MessageSeverity Severity, String^ description)
{
    marshal_context^ context = gcnew marshal_context();
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->AddApplicationMessage(static_cast<D3D11_MESSAGE_SEVERITY>(Severity), context->marshal_as<const char*>(description)));
}

void InfoQueue::AddMessage(MessageCategory Category, MessageSeverity Severity, MessageId ID, String^ description)
{
    marshal_context^ context = gcnew marshal_context();
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->AddMessage(static_cast<D3D11_MESSAGE_CATEGORY>(Category), static_cast<D3D11_MESSAGE_SEVERITY>(Severity), static_cast<D3D11_MESSAGE_ID>(ID), context->marshal_as<const char*>(description)));
}

void InfoQueue::AddRetrievalFilterEntries(InfoQueueFilter^ Filter)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->AddRetrievalFilterEntries(Filter->nativeObject.Get()));
}

void InfoQueue::AddStorageFilterEntries(InfoQueueFilter^ Filter)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->AddStorageFilterEntries(Filter->nativeObject.Get()));
}

void InfoQueue::ClearRetrievalFilter()
{
    GetInterface<ID3D11InfoQueue>()->ClearRetrievalFilter();
}

void InfoQueue::ClearStorageFilter()
{
    GetInterface<ID3D11InfoQueue>()->ClearStorageFilter();
}

void InfoQueue::ClearStoredMessages()
{
    GetInterface<ID3D11InfoQueue>()->ClearStoredMessages();
}

Boolean InfoQueue::GetBreakOnCategory(MessageCategory Category)
{
    BOOL returnValue = GetInterface<ID3D11InfoQueue>()->GetBreakOnCategory(static_cast<D3D11_MESSAGE_CATEGORY>(Category));
    return returnValue != 0;
}

Boolean InfoQueue::GetBreakOnID(MessageId ID)
{
    BOOL returnValue = GetInterface<ID3D11InfoQueue>()->GetBreakOnID(static_cast<D3D11_MESSAGE_ID>(ID));
    return returnValue != 0;
}

Boolean InfoQueue::GetBreakOnSeverity(MessageSeverity Severity)
{
    BOOL returnValue = GetInterface<ID3D11InfoQueue>()->GetBreakOnSeverity(static_cast<D3D11_MESSAGE_SEVERITY>(Severity));
    return returnValue != 0;
}

Message^ InfoQueue::GetMessage(UInt64 messageIndex)
{
    // Get the size of the message
    SIZE_T messageLength = 0;
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetMessage(static_cast<UINT64>(messageIndex), NULL, &messageLength));

    // Allocate space and get the message
    D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength);
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetMessage(static_cast<UINT64>(messageIndex), pMessage, &messageLength));

    return pMessage == NULL ? nullptr : gcnew Message(pMessage, false); // poinhter will be disposed in the Message's finalizer
}

 bool InfoQueue::TryGetMessage(UInt64 messageIndex, [Runtime::InteropServices::Out]  Message^ % outMessage)
{
    outMessage = nullptr;

    // Get the size of the message
    SIZE_T messageLength = 0;
    if (FAILED(GetInterface<ID3D11InfoQueue>()->GetMessage(static_cast<UINT64>(messageIndex), NULL, &messageLength)))
    {
        return false;
    }

    // Allocate space and get the message
    D3D11_MESSAGE * pMessage = (D3D11_MESSAGE*)malloc(messageLength);
    if (SUCCEEDED(GetInterface<ID3D11InfoQueue>()->GetMessage(static_cast<UINT64>(messageIndex), pMessage, &messageLength)))
    {
        outMessage = pMessage == NULL ? nullptr : gcnew Message(pMessage, false); // poinhter will be disposed in the Message's finalizer
        return true;
    }
    else
    {
        return false;
    }
}
UInt64 InfoQueue::GetMessageCountLimit()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetMessageCountLimit();
    return safe_cast<UInt64>(returnValue);
}

Boolean InfoQueue::GetMuteDebugOutput()
{
    BOOL returnValue = GetInterface<ID3D11InfoQueue>()->GetMuteDebugOutput();
    return returnValue != 0;
}

UInt64 InfoQueue::GetNumMessagesAllowedByStorageFilter()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetNumMessagesAllowedByStorageFilter();
    return safe_cast<UInt64>(returnValue);
}

UInt64 InfoQueue::GetNumMessagesDeniedByStorageFilter()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetNumMessagesDeniedByStorageFilter();
    return safe_cast<UInt64>(returnValue);
}

UInt64 InfoQueue::GetNumMessagesDiscardedByMessageCountLimit()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetNumMessagesDiscardedByMessageCountLimit();
    return safe_cast<UInt64>(returnValue);
}

UInt64 InfoQueue::GetNumStoredMessages()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetNumStoredMessages();
    return static_cast<UInt64>(returnValue);
}

UInt64 InfoQueue::GetNumStoredMessagesAllowedByRetrievalFilter()
{
    UINT64 returnValue = GetInterface<ID3D11InfoQueue>()->GetNumStoredMessagesAllowedByRetrievalFilter();
    return safe_cast<UInt64>(returnValue);
}

InfoQueueFilter^ InfoQueue::GetRetrievalFilter()
{
    SIZE_T size = 0;
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetRetrievalFilter(NULL, &size));

    D3D11_INFO_QUEUE_FILTER * filter = (D3D11_INFO_QUEUE_FILTER*)malloc(size);
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetRetrievalFilter(filter, &size));

    return filter == NULL ? nullptr : gcnew InfoQueueFilter(filter, false); // poinhter will be disposed in the Message's finalizer
}

UInt32 InfoQueue::GetRetrievalFilterStackSize()
{
    return GetInterface<ID3D11InfoQueue>()->GetRetrievalFilterStackSize();
}

InfoQueueFilter^ InfoQueue::GetStorageFilter()
{

    SIZE_T size = 0;
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetStorageFilter(NULL, &size));

    D3D11_INFO_QUEUE_FILTER * filter = (D3D11_INFO_QUEUE_FILTER*)malloc(size);
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->GetStorageFilter(filter, &size));

    return filter == NULL ? nullptr : gcnew InfoQueueFilter(filter, false); // poinhter will be disposed in the Message's finalizer
}

UInt32 InfoQueue::GetStorageFilterStackSize()
{
    return GetInterface<ID3D11InfoQueue>()->GetStorageFilterStackSize();
}

void InfoQueue::PopRetrievalFilter()
{
    GetInterface<ID3D11InfoQueue>()->PopRetrievalFilter();
}

void InfoQueue::PopStorageFilter()
{
    GetInterface<ID3D11InfoQueue>()->PopStorageFilter();
}

void InfoQueue::PushCopyOfRetrievalFilter()
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushCopyOfRetrievalFilter());
}

void InfoQueue::PushCopyOfStorageFilter()
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushCopyOfStorageFilter());
}

void InfoQueue::PushEmptyRetrievalFilter()
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushEmptyRetrievalFilter());
}

void InfoQueue::PushEmptyStorageFilter()
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushEmptyStorageFilter());
}

void InfoQueue::PushRetrievalFilter(InfoQueueFilter^ Filter)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushRetrievalFilter(Filter->nativeObject.Get()));
}

void InfoQueue::PushStorageFilter(InfoQueueFilter^ Filter)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->PushStorageFilter(Filter->nativeObject.Get()));
}

void InfoQueue::SetBreakOnCategory(MessageCategory Category, Boolean bEnable)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->SetBreakOnCategory(static_cast<D3D11_MESSAGE_CATEGORY>(Category), safe_cast<BOOL>(bEnable)));
}

void InfoQueue::SetBreakOnID(MessageId ID, Boolean bEnable)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->SetBreakOnID(static_cast<D3D11_MESSAGE_ID>(ID), safe_cast<BOOL>(bEnable)));
}

void InfoQueue::SetBreakOnSeverity(MessageSeverity Severity, Boolean bEnable)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->SetBreakOnSeverity(static_cast<D3D11_MESSAGE_SEVERITY>(Severity), safe_cast<BOOL>(bEnable)));
}

void InfoQueue::SetMessageCountLimit(UInt64 MessageCountLimit)
{
    CommonUtils::VerifyResult(GetInterface<ID3D11InfoQueue>()->SetMessageCountLimit(safe_cast<UINT64>(MessageCountLimit)));
}

void InfoQueue::SetMuteDebugOutput(Boolean bMute)
{
    GetInterface<ID3D11InfoQueue>()->SetMuteDebugOutput(safe_cast<BOOL>(bMute));
}

